using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;

namespace GameFramework.Audio
{
    public class AudioManager : GameComponent
    {
        #region Singleton
        /// <summary>
        /// The singleton for this type
        /// </summary>
        private static AudioManager _instance = null;
        #endregion

        /*data*/
        private Dictionary<string, SoundEffectInstance> _sounds;
        private Dictionary<string, Song> _songs;

        private List<string> _sound_list;
        private int _sound_list_index;
        public static bool IsMultiSoundPlaying
        {
            get
            {
                return _instance._is_playing_multi;
            }
            
        }
        private bool _is_playing_multi = false;

        private bool _enableSoundEffects;
        public static bool EnableSoundEffects
        {
            get
            {
                return _instance._enableSoundEffects;
            }
            set
            {
                _instance._enableSoundEffects = value;
            }
        }

        private bool _enableBackgroundMusic;
        public static bool EnableBackgroundMusic
        {
            get
            {
                return _instance._enableBackgroundMusic;
            }
            set
            {
                _instance._enableBackgroundMusic = value;
            }
        }
        private AudioManager(Game game)
            : base(game)
        {

        }


        public static void Initialize(Game game)
        {
            _instance = new AudioManager(game);
            if (game != null)
            {
                game.Components.Add(_instance);
            }
            _instance._sounds = new Dictionary<string, SoundEffectInstance>();
            _instance._songs = new Dictionary<string, Song>();
            _instance._enableSoundEffects = true;
            _instance._enableBackgroundMusic = true;
            _instance._sound_list = new List<string>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="soundInstance"></param>
        public static void AddSound(string name, SoundEffectInstance soundInstance)
        {
            if (_instance._sounds.ContainsKey(name))
            {
                System.Diagnostics.Debug.Assert(true, "the same name was detect");
            }
            else
            {
                _instance._sounds.Add(name, soundInstance);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="song"></param>
        public static void AddSong(string name, Song song)
        {
            if (_instance._songs.ContainsKey("name"))
            {
                System.Diagnostics.Debug.Assert(true, "the same name was detect");
            }
            else
            {
                _instance._songs.Add(name, song);
            }
        }

        public static void StopSong()
        {
            if (MediaPlayer.GameHasControl)
                MediaPlayer.Stop();
        }

        public static void PauseSong()
        {
            if (MediaPlayer.GameHasControl)
                MediaPlayer.Pause();
        }
        public static void ResumeSong()
        {
            if (_instance._enableBackgroundMusic)
            {
                if (MediaPlayer.GameHasControl)
                    MediaPlayer.Resume();
            }
        }

        public static void PlaySound(string soundName,bool isLoop)
        {
            if (!_instance._enableSoundEffects)
            {
                return;
            }
            if (_instance._sounds.ContainsKey(soundName))
            {
                if (_instance._sounds[soundName].IsLooped != isLoop)
                {
                    _instance._sounds[soundName].IsLooped = isLoop;
                }

                if (_instance._sounds[soundName].State != SoundState.Stopped)
                {
                    _instance._sounds[soundName].Stop(true);
                }

                _instance._sounds[soundName].Play();
            }
            else
            {
                System.Diagnostics.Debug.Assert(true, "Sound not found");
            }
        }

        public static void PlaySong(string songName, bool isLoop)
        {
            if (!_instance._enableBackgroundMusic)
            {
                return;
            }

            if (_instance._songs.ContainsKey(songName))
            {
                if (MediaPlayer.GameHasControl)
                {
                    MediaPlayer.IsRepeating = isLoop;
                    MediaPlayer.Play(_instance._songs[songName]);
                }
            }
            else
            {
                System.Diagnostics.Debug.Assert(true, "Song not found");
            }
        }

        public override void Update(GameTime gameTime)
        {

            if (_instance._is_playing_multi)
            {
                if (_sounds[_instance._sound_list[_instance._sound_list_index]].State == SoundState.Stopped)
                {
                    _instance._sound_list_index++;
                    if (_instance._sound_list_index >= _instance._sound_list.Count)//finished
                    {
                        ResetMultiSounds();
                    }
                    else
                    {
                        PlaySound(_instance._sound_list[_instance._sound_list_index], false);
                    }
                }
            }
            base.Update(gameTime);
        }
        /// <summary>
        /// true: sounds success
        /// false:  sounds play fail
        /// </summary>
        /// <param name="sounds"></param>
        /// <returns></returns>
        public static bool PlaySounds(string[] sounds)
        {
            if (_instance._is_playing_multi)
            {
                System.Diagnostics.Debug.Assert(true, "Multi sounds is on playing");
                return false;
            }

            _instance._sound_list.Clear();

            //processing for number
            for (int i = 0; i < sounds.Length; i++)
            {
                string sound = sounds[i];
                if (string.Compare(sound, 0, "#", 0, 1) == 0)//it is number
                {
                    List<char> sound_char = sound.ToList<char>();
                    sound_char.RemoveAt(0);

                    switch(sound_char.Count)
                    {
                        case 1:
                            _instance._sound_list.Add(sound_char[0].ToString());
                            break;
                        case 2:
                            if (sound_char[1] == '0')
                            {
                                if (sound_char[0] == '1')
                                {
                                    _instance._sound_list.Add("10");
                                }
                                else
                                {
                                    _instance._sound_list.Add(sound_char[0].ToString());
                                    _instance._sound_list.Add("muoi");
                                }
                            }
                            else
                            {
                                if (sound_char[0] == '1')
                                {
                                    _instance._sound_list.Add("10");
                                    _instance._sound_list.Add(sound_char[1].ToString());
                                }
                                else
                                {
                                    _instance._sound_list.Add(sound_char[0].ToString());
                                    _instance._sound_list.Add("muoi");
                                    _instance._sound_list.Add(sound_char[1].ToString());
                                }
                            }
                            break;
                        case 3://100
                            _instance._sound_list.Add("100");
                            break;
                    }
                }
                else
                {
                    _instance._sound_list.Add(sound);
                }
            }

            
            ResetMultiSounds();
            _instance._is_playing_multi = true;
            PlaySound(_instance._sound_list[_instance._sound_list_index], false);
            return true;
        }

        private static void ResetMultiSounds()
        {
            _instance._sound_list_index = 0;
            _instance._is_playing_multi = false;
        }

    }
}
